﻿using System;
using System.Collections.Generic;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using YArchitech.Controls;
using YJKArchMethodLibrary.Utils;
using YJKElementFinish.ColumnSurface.DataDefinition;

namespace YJKElementFinish.ColumnSurface.Managers
{
	public class WallTypeManager
	{
		public static WallType GetWallType(string wallTypeName, WallType refWallType, List<CompoundStructureLayer> layers, Document doc, bool updateStructureLayer = false)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			ICollection<Element> collection = filteredElementCollector.OfClass(typeof(WallType)).ToElements();
			foreach (Element element in collection)
			{
				WallType wallType = element as WallType;
				if (wallType.Kind == null)
				{
					if (refWallType == null)
					{
						refWallType = wallType;
					}
					if (wallTypeName.CompareTo(wallType.Name) == 0)
					{
						if (updateStructureLayer && !WallTypeManager.UpdateStructureLayer(wallType, layers, doc))
						{
							return null;
						}
						return wallType;
					}
				}
			}
			List<CompoundStructureLayer> list = new List<CompoundStructureLayer>();
			foreach (CompoundStructureLayer compoundStructureLayer in layers)
			{
				if (compoundStructureLayer != null)
				{
					list.Add(compoundStructureLayer);
				}
			}
			WallType wallType2 = refWallType.Duplicate(wallTypeName) as WallType;
			if (!WallTypeManager.UpdateCompoundStructure(wallType2, list, doc))
			{
				doc.Delete(wallType2.Id);
				return null;
			}
			return wallType2;
		}

		public static List<WallTypeLayerInfos> GetSurfaceLayerWallType(Document doc)
		{
			List<WallTypeLayerInfos> list = new List<WallTypeLayerInfos>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			ICollection<Element> collection = filteredElementCollector.OfClass(typeof(WallType)).ToElements();
			foreach (Element element in collection)
			{
				WallType wallType = element as WallType;
				WallTypeLayerInfos wallLayerInfoListByType = WallTypeManager.GetWallLayerInfoListByType(wallType, doc);
				if (wallLayerInfoListByType != null)
				{
					bool flag = false;
					foreach (WallLayerInfos wallLayerInfos in wallLayerInfoListByType.LayerList)
					{
                        if (wallLayerInfos.StructureLayer.Function == (MaterialFunctionAssignment)1)
						{
							flag = true;
							break;
						}
					}
					if (!flag)
					{
						list.Add(wallLayerInfoListByType);
					}
				}
			}
			return list;
		}

		public static WallTypeLayerInfos GetWallLayerInfoListByType(HostObjAttributes wallType, Document doc)
		{
			CompoundStructure compoundStructure = wallType.GetCompoundStructure();
			if (compoundStructure == null)
			{
				return null;
			}
			int firstCoreLayerIndex = compoundStructure.GetFirstCoreLayerIndex();
			int lastCoreLayerIndex = compoundStructure.GetLastCoreLayerIndex();
            compoundStructure.GetNumberOfShellLayers((ShellLayerType)1);
            compoundStructure.GetNumberOfShellLayers((ShellLayerType)0);
			List<WallLayerInfos> list = new List<WallLayerInfos>();
			IList<CompoundStructureLayer> layers = compoundStructure.GetLayers();
			for (int i = 0; i < layers.Count; i++)
			{
				CompoundStructureLayer compoundStructureLayer = layers[i];
				string layerNameByMaterialFunction = WallTypeManager.GetLayerNameByMaterialFunction(compoundStructureLayer.Function);
				string materialName = WallTypeManager.GetMaterialName(compoundStructureLayer, doc);
				string thickness = Common.FeetToMM(compoundStructureLayer.Width).ToString();
				WallLayerInfos item = new WallLayerInfos(compoundStructureLayer, layerNameByMaterialFunction, materialName, thickness);
				list.Add(item);
			}
			return new WallTypeLayerInfos(wallType.Name, firstCoreLayerIndex, lastCoreLayerIndex, list);
		}

		public static WallTypeLayerInfos GetWallLayerInfoListByType(HostObjAttributes wallType, Document doc, double thick)
		{
			CompoundStructure compoundStructure = wallType.GetCompoundStructure();
			if (compoundStructure == null)
			{
				return null;
			}
			int firstCoreLayerIndex = compoundStructure.GetFirstCoreLayerIndex();
			int lastCoreLayerIndex = compoundStructure.GetLastCoreLayerIndex();
            compoundStructure.GetNumberOfShellLayers((ShellLayerType)1);
            compoundStructure.GetNumberOfShellLayers((ShellLayerType)0);
			List<WallLayerInfos> list = new List<WallLayerInfos>();
			IList<CompoundStructureLayer> layers = compoundStructure.GetLayers();
			for (int i = 0; i < layers.Count; i++)
			{
				CompoundStructureLayer compoundStructureLayer = layers[i];
				string layerNameByMaterialFunction = WallTypeManager.GetLayerNameByMaterialFunction(compoundStructureLayer.Function);
				string materialName = WallTypeManager.GetMaterialName(compoundStructureLayer, doc);
				string thickness = Common.FeetToMM(thick).ToString();
				WallLayerInfos item = new WallLayerInfos(compoundStructureLayer, layerNameByMaterialFunction, materialName, thickness);
				list.Add(item);
			}
			return new WallTypeLayerInfos(wallType.Name, firstCoreLayerIndex, lastCoreLayerIndex, list);
		}

		public static bool GetErrorStringByCompoundStructureErrorMap(IDictionary<int, CompoundStructureError> errMap, List<CompoundStructureLayer> layers, ref string message)
		{
			if (errMap.Count > 0)
			{
				CompoundStructureError value = errMap.First<KeyValuePair<int, CompoundStructureError>>().Value;
				int key = errMap.First<KeyValuePair<int, CompoundStructureError>>().Key;
				if (key != -1)
				{
					message = "第" + (key + 1).ToString() + "层，";
				}
                switch ((int)value)
				{
				case 0:
					message += "层功能优先级不能从核心边界提高到面层面上";
					break;
				case 1:
					message += "核心层包含一个镀膜层或核心层厚度为零";
					break;
				case 3:
					message += "镀膜层厚度大于零";
					break;
				case 4:
					message += "非膜层厚度太薄";
					break;
				case 5:
					message += "外壳层层数大于总层数";
					break;
				case 6:
                    if (layers[key].Function != (MaterialFunctionAssignment)100)
					{
						message += "外层厚度太薄";
					}
					else if (errMap.Count == 1)
					{
						return false;
					}
					break;
				case 7:
					message += "非膜层厚度为零";
					break;
				case 8:
					message += "层不能在核心边界的同一侧";
					break;
				case 9:
					message += "外层边界在某些高度有多于一个表面";
					break;
				case 10:
					message += "内核边界在某些高度有多于一个表面";
					break;
				case 11:
					message += "镀膜层在某些高度有多于一个表面";
					break;
				case 12:
					message += "顶部缺少结构层或者厚度太薄";
					break;
				case 13:
					message += "底部缺少结构层或者厚度太薄";
					break;
				case 14:
					message += "可变厚度层厚度为零";
					break;
				case 15:
					message += "元素的ID作为材料标识不符合实际的材质实体";
					break;
				case 16:
					message += "外延层上方的墙必须是相邻的";
					break;
				case 17:
					message += "外延层底部的墙必须是相邻的";
					break;
				case 18:
					message += "元素的ID作为轮廓标识不符合一个有效的结构剖面";
					break;
				}
				return true;
			}
			return false;
		}

		public static bool IsValidWithLayers(List<CompoundStructureLayer> layers, Document doc, ref string message)
		{
			if (layers.Count == 0)
			{
				message = "结构层数量不能为零";
				return false;
			}
			CompoundStructure compoundStructure = null;
			try
			{
				compoundStructure = CompoundStructure.CreateSimpleCompoundStructure(layers);
			}
			catch (Exception)
			{
				message = "非镀膜层厚度不能为零";
				return false;
			}
			IDictionary<int, CompoundStructureError> errMap = null;
			IDictionary<int, int> dictionary = null;
            return compoundStructure.IsValid(doc, out errMap, out dictionary) || !WallTypeManager.GetErrorStringByCompoundStructureErrorMap(errMap, layers, ref message);
		}

		public static string GetTypeNameByLayers(List<WallLayerInfos> layers)
		{
			string text = "";
			string text2 = "";
			for (int i = 0; i < layers.Count; i++)
			{
				if (layers[i].StructureLayer != null && Geometry.GreaterThan(layers[i].StructureLayer.Width, 0.0))
				{
					text = text + layers[i].MaterialName + " ";
					text2 = text2 + layers[i].Thickness + " ";
				}
			}
			string text3 = "HY-" + text + text2;
			return text3.TrimEnd(new char[0]);
		}

		public static string GetTypeNameByLayers(List<CompoundStructureLayer> layers, Document doc)
		{
			string text = "";
			string text2 = "";
			for (int i = 0; i < layers.Count; i++)
			{
				if (Geometry.GreaterThan(layers[i].Width, 0.0))
				{
					text = text + WallTypeManager.GetMaterialName(layers[i], doc) + " ";
					text2 = text2 + AssistFunc.feetToMM(layers[i].Width).ToString("f0") + " ";
				}
			}
			string text3 = "HY-" + text + text2;
			return text3.TrimEnd(new char[0]);
		}

		public static string GetNoRepetitionName(string baseName, Document doc)
		{
            //WallTypeManager.<>c__DisplayClass2 <>c__DisplayClass = new WallTypeManager.<>c__DisplayClass2();
			List<string> list = new List<string>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			ICollection<Element> collection = filteredElementCollector.OfClass(typeof(WallType)).ToElements();
			foreach (Element element in collection)
			{
				WallType wallType = element as WallType;
				list.Add(wallType.Name);
			}
            //<>c__DisplayClass.res = "";
			int num = 0;
			for (;;)
			{
                //<>c__DisplayClass.res = baseName;
                //if (num != 0)
                //{
                //    WallTypeManager.<>c__DisplayClass2 <>c__DisplayClass2 = <>c__DisplayClass;
                //    <>c__DisplayClass2.res = <>c__DisplayClass2.res + "(" + num.ToString() + ")";
                //}
                //int num2 = list.FindIndex((string value) => value.CompareTo(<>c__DisplayClass.res) == 0);
                //if (num2 == -1)
                //{
                //    break;
                //}
                //num++;
			}
			//return <>c__DisplayClass.res;
			return "";
		}

		public static bool UpdateStructureLayer(WallType wallType, List<CompoundStructureLayer> layers, Document doc)
		{
			CompoundStructure compoundStructure = wallType.GetCompoundStructure();
			IList<CompoundStructureLayer> layers2 = compoundStructure.GetLayers();
			if (layers2.Count != layers.Count)
			{
				return WallTypeManager.UpdateCompoundStructure(wallType, layers, doc);
			}
			int i = 0;
			bool flag = true;
			while (i < layers2.Count)
			{
				CompoundStructureLayer compoundStructureLayer = layers2[i];
				CompoundStructureLayer compoundStructureLayer2 = layers[i];
				if (compoundStructureLayer.Function != compoundStructureLayer2.Function || !Geometry.IsEqual(compoundStructureLayer.Width, compoundStructureLayer2.Width) || compoundStructureLayer.MaterialId.IntegerValue != compoundStructureLayer2.MaterialId.IntegerValue)
				{
					flag = false;
					break;
				}
				i++;
			}
			return flag || WallTypeManager.UpdateCompoundStructure(wallType, layers, doc);
		}

		public static string GetLayerNameByMaterialFunction(MaterialFunctionAssignment function)
		{
			string result = "";
            switch ((int)function)
			{
			case 1:
				result = "结构";
				break;
			case 2:
				result = "衬底";
				break;
			case 3:
				result = "保温层/空气层";
				break;
			case 4:
				result = "面层1";
				break;
			case 5:
				result = "面层2";
				break;
			default:
                if ((int)function != 100)
				{
                    if ((int)function == 200)
					{
						result = "结构装饰";
					}
				}
				else
				{
					result = "涂膜层";
				}
				break;
			}
			return result;
		}

		public static MaterialFunctionAssignment GetLayerMaterialFunctionByName(string name)
		{
			MaterialFunctionAssignment result = 0;
			switch (name)
			{
			case "面层1":
                    result = (MaterialFunctionAssignment)4;
				break;
			case "面层2":
                result = (MaterialFunctionAssignment)5;
				break;
			case "保温层/空气层":
                result = (MaterialFunctionAssignment)3;
				break;
			case "涂膜层":
                result = (MaterialFunctionAssignment)100;
				break;
			case "结构装饰":
                result = (MaterialFunctionAssignment)200;
				break;
			case "结构":
                result = (MaterialFunctionAssignment)1;
				break;
			case "衬底":
                result = (MaterialFunctionAssignment)2;
				break;
			}
			return result;
		}

		public static ElementId GetMaterialIdByName(string name, Document doc)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(Material));
			FilteredElementIterator elementIterator = filteredElementCollector.GetElementIterator();
			elementIterator.Reset();
			while (elementIterator.MoveNext())
			{
				Element element = elementIterator.Current;
				Material material = element as Material;
				if (material.Name.Contains(name))
				{
					return material.Id;
				}
			}
			return ElementId.InvalidElementId;
		}

		private static string GetMaterialName(CompoundStructureLayer layer, Document doc)
		{
			ElementId materialId = layer.MaterialId;
			if (materialId == ElementId.InvalidElementId || null == materialId)
			{
				return "按类别";
			}
			Element element = doc.GetElement(materialId);
			Material material = element as Material;
			return material.Name;
		}

		public static bool UpdateCompoundStructure(HostObjAttributes newWallType, List<CompoundStructureLayer> realLayers, Document doc)
		{
			bool result;
			try
			{
				double num = Common.MMToFeet(1000.0);
				WallType wallType = newWallType as WallType;
				if (realLayers.Count == 1 && wallType != null)
				{
					MaterialFunctionAssignment function = realLayers[0].Function;
					double width = realLayers[0].Width;
					if (Geometry.IsEqual(width, 0.0))
					{
						return false;
					}
					ElementId materialId = realLayers[0].MaterialId;
					CompoundStructure compoundStructure = CompoundStructure.CreateSingleLayerCompoundStructure(num, function, width, materialId);
					newWallType.SetCompoundStructure(compoundStructure);
				}
				else
				{
					CompoundStructure compoundStructure2 = newWallType.GetCompoundStructure();
					compoundStructure2.SetLayers(realLayers);
					int i = 0;
					int num2 = -1;
					int num3 = -1;
					while (i < realLayers.Count)
					{
                        if ((int)realLayers[i].Function == 1)
						{
							if (num2 == -1)
							{
								num2 = i;
							}
							num3 = i;
						}
						i++;
					}
					if (num2 == -1)
					{
                        compoundStructure2.SetNumberOfShellLayers((ShellLayerType)0, 0);
                        compoundStructure2.SetNumberOfShellLayers((ShellLayerType)1, 0);
					}
					else if (num2 == num3)
					{
                        compoundStructure2.SetNumberOfShellLayers((ShellLayerType)0, num2);
                        compoundStructure2.SetNumberOfShellLayers((ShellLayerType)1, realLayers.Count - num2 - 1);
					}
					else
					{
                        compoundStructure2.SetNumberOfShellLayers((ShellLayerType)0, num2);
                        compoundStructure2.SetNumberOfShellLayers((ShellLayerType)1, realLayers.Count - num3 - 1);
					}
					IDictionary<int, CompoundStructureError> errMap = null;
					IDictionary<int, int> dictionary = null;
                    if (compoundStructure2.IsValid(doc, out errMap, out dictionary))
					{
						newWallType.SetCompoundStructure(compoundStructure2);
						string text = "";
						WallTypeManager.GetErrorStringByCompoundStructureErrorMap(errMap, realLayers, ref text);
					}
					else
					{
                        compoundStructure2.SetNumberOfShellLayers((ShellLayerType)0, 0);
                        compoundStructure2.SetNumberOfShellLayers((ShellLayerType)1, 0);
                        if (compoundStructure2.IsValid(doc, out errMap, out dictionary))
						{
							newWallType.SetCompoundStructure(compoundStructure2);
						}
					}
				}
				result = true;
			}
			catch (Exception ex)
			{
				YJKMessageBox.Show(ex.Message);
				result = false;
			}
			return result;
		}
	}
}
